﻿using Library.Collections.Specialized;
using Library.Linq;
using Library.Logic.Constraints;
using Library.Logic.Inference;
using Library.Transactions;
using System;
using System.Linq.Expressions;
using TRULE = System.Linq.Expressions.Expression<System.Func<System.Linq.IQueryable<System.Linq.Expressions.Expression>, System.Collections.Generic.IEnumerable<System.Collections.Generic.IEnumerable<System.Linq.Expressions.Expression>>>>;
using TEXPRESSION = System.Linq.Expressions.Expression;

namespace Library.Logic.Transactional
{
    public static class Transactional
    {
        public static ITransaction<bool> Add(this IConstraintsReason obj, TEXPRESSION constraint)
        {
            ICollectionTransactionable<Expression> transactionable = obj as ICollectionTransactionable<Expression>;
            if (transactionable != null)
                return transactionable.Add(constraint);

            if (!obj.Add(constraint)) return Scope.False;
            return new ScopeAction(true, () => obj.Remove(constraint));
        }
        public static ITransaction<bool> Remove(this IConstraintsReason obj, TEXPRESSION constraint)
        {
            ICollectionTransactionable<Expression> transactionable = obj as ICollectionTransactionable<Expression>;
            if (transactionable != null)
                return transactionable.Remove(constraint);

            if (!obj.Remove(constraint)) return Scope.False;
            return new ScopeAction(true, () => obj.Add(constraint));
        }

        public static ITransaction<bool> Unify(this IHasConstraintsReason obj, object[] value)
        {
            throw new NotImplementedException();
        }
        public static ITransaction<bool> Unify(this IHasConstraintsReason obj, object[] value, out IInference argument)
        {
            throw new NotImplementedException();
        }

        public static ITransaction<bool> EnsureEntails(this IConstraintsReason obj, TEXPRESSION expression, IReasonerReadOnly<TEXPRESSION, TRULE> reasoner)
        {
            if (reasoner.Reason(obj).Contains(expression)) return Scope.True;
            else
            {
                if (!obj.Add(expression)) return Scope.False;
                return new ScopeAction(true, () => obj.Remove(expression));
            }
        }
    }
}
